/**
 * @Copyright ®2015 Sinosoft Co. Ltd. All rights reserved.<br/>
 * 项目名称 : 中科软支付平台
 * 创建日期 : 2016年12月30日
 * 修改历史 : 
 *     1. [2016年12月30日]创建文件 by liuyujia
 */
package com.sinosoft.sinopay.web.agentpay.web.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.security.KeyStore;
import java.security.Signature;
import java.security.interfaces.RSAPrivateCrtKey;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.sinosoft.sinocloud.platform.base.SinoBaseController;
import com.sinosoft.sinocloud.platform.base.SinoBaseController.JsonType;
import com.sinosoft.sinocloud.platform.common.util.DateUtil;
import com.sinosoft.sinocloud.platform.common.util.SecurityUtil;
import com.sinosoft.sinopay.api.common.dto.pay.PaymentInfoDetailDTO;
import com.sinosoft.sinopay.payrules.config.ENUM_PAY_TYPE;
import com.sinosoft.sinopay.web.agentpay.biz.config.AgentConfig;
import com.sinosoft.sinopay.web.agentpay.biz.service.AgentSecurityService;
import com.sinosoft.sinopay.web.agentpay.biz.service.PaymentAgentService;
import com.sinosoft.sinopay.web.agentpay.dto.TongRequestDTO;
import com.sinosoft.sinopay.web.util.FilePathUtil;

/**  
 * 【代理网关支付页面请求Controller】
 * @author liuyujia
 * @date 2016年12月30日 下午2:11:11 
 * @version V1.0  
 */
@Controller
@RequestMapping("/sinopay/agentPay")
public class AgentPayController extends SinoBaseController{
	@Autowired
	private AgentSecurityService agentSecurityService;
	@Autowired
	private PaymentAgentService paymentAgentService;
	
	@RequestMapping(value = "tongpay.do", method = RequestMethod.POST)
	public void agentPay(HttpServletRequest request, HttpServletResponse response){
		try{
			//1.获取返回参数
        	String payNo = request.getParameter("payNo");
            String tSignMsg = request.getParameter("sign");
            String terminalType = request.getParameter("terminal_type");
            String tbizNo = request.getParameter("bizNo");
            String tPayWay = ENUM_PAY_TYPE.AGENTPAY.code();
            //2.验证签名 
            agentSecurityService.checkPayNoSignValid(payNo, tPayWay, tSignMsg);
            //3.判断支付订单号支付状态 
            agentSecurityService.checkPayStatus(payNo);
            //4.获取支付订单信息
			PaymentInfoDetailDTO tPaymentInfoDetailDTO = paymentAgentService.getPaymentTradeForPayNo(payNo);
			String cstno = paymentAgentService.getCustomerNo(tPaymentInfoDetailDTO);
			String orderTime =DateUtil.getDateStr(new Date(), "yyyyMMddHHmmss");
			//5.写主表信息
			paymentAgentService.addPaymentInfo(payNo);
			//6.封装请求参数
			AgentConfig tAgentConfig = new AgentConfig();
	        TongRequestDTO tongRequestDTO = new TongRequestDTO();
	        tongRequestDTO.setSign_type(tAgentConfig.getSignType());
	        tongRequestDTO.setMer_id(tAgentConfig.getMerId());
	        tongRequestDTO.setApp_id(tongRequestDTO.getMer_id());
	        tongRequestDTO.setOrder_no(payNo);
	        tongRequestDTO.setOrder_amt(String.valueOf(tPaymentInfoDetailDTO.getPayAmount().intValue()));
	        tongRequestDTO.setNotify_url(tAgentConfig.getNotifyUrl());//后台
	        tongRequestDTO.setReturn_url(tAgentConfig.getReturnUrl());//前台
	        tongRequestDTO.setVersion(tAgentConfig.getVersion());
	        tongRequestDTO.setService(tAgentConfig.getService());
	        tongRequestDTO.setTerminal_type(terminalType);
	        if(terminalType.equals("web")){
	        	tongRequestDTO.setCstno(cstno);//PC
	        }else{
	        	tongRequestDTO.setCst_no(cstno);//移动
	        }
	        tongRequestDTO.setOrder_time(orderTime);
	        tongRequestDTO.setTimestamp(orderTime);
	        //非必填
	        tongRequestDTO.setTrade_code(tAgentConfig.getTradeCode());
	        tongRequestDTO.setCur_type(tAgentConfig.getCurType());
	        tongRequestDTO.setGoods_name(tPaymentInfoDetailDTO.getTradeDesc());
	        tongRequestDTO.setGoods_num("1");
	        tongRequestDTO.setGoods_type(tAgentConfig.getGoodsType());
	        tongRequestDTO.setLogistics(tAgentConfig.getLogistics());
	        tongRequestDTO.setAddress("");
	        tongRequestDTO.setRemark("");
	        tongRequestDTO.setTerminal_info("");
	        tongRequestDTO.setCard_holder_name("");
	        tongRequestDTO.setCre_no("");
	        //对象转Map
	        Map<String, Object> tongMap = objectToMap(tongRequestDTO, true);
	        Map<String, String> transMap = paraFilter(tongMap);
	        //签名
	        String Sign = buildRequestMysign(transMap);
	        tongRequestDTO.setSign(Sign);
	        transMap.put("sign_type", tongRequestDTO.getSign_type());
	        transMap.put("sign",Sign);
	        this.renderJsonData(transMap, JsonType.JSON_OBJECT, request, response);
		}
		catch(Exception ex){
			ex.printStackTrace();
		}
	}

	/**
	 * 把对象转换为Map对象
	 * @param object
	 * @param isNullConvert
	 * @return
	 * @throws Exception
	 */
	private Map<String, Object> objectToMap(Object object, boolean isNullConvert) throws Exception {
    	Map<String, Object> map = new HashMap<String, Object>();
	    Field[] fields = object.getClass().getDeclaredFields();
	    Object obj = null;
	    for (Field field : fields) {
	        field.setAccessible(true);
	        obj = field.get(object);
	        /*
	         * 通过传入参数isNullConvert判断是否把Object中属性值为null的值进行转换。
	         * 当为ture时，将object中所有属性转换为map对象key-value
	         * 当为false时，只把object中的属性值不为null的属性进行转换成mapz对象的key-value
	         */
	        if (isNullConvert) {
	            map.put(field.getName(), obj);
	        } else if (obj != null) {
	            map.put(field.getName(), obj);
	        }
	    }
	    return map;
	}
	
	/**
	 * 除去数组中的空值和签名参数
	 * @param sArray
	 * @return
	 */
	public static Map<String, String> paraFilter(Map<String, Object> sArray) {
        Map<String, String> result = new HashMap<String, String>();
        if (sArray == null || sArray.size() <= 0) {
            return result;
        }
        for (String key : sArray.keySet()) {
            Object value = sArray.get(key);
            if (value == null || value.equals("") || key.equalsIgnoreCase("sign")
                || key.equalsIgnoreCase("sign_type")) {
                continue;
            }
            result.put(key, value.toString());
        }
        return result;
    }
	
	public String buildRequestMysign(Map<String, String> sPara) {
        String prestr = createLinkString(sPara); //把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
        System.out.println("签名前参数:" + prestr);
        String mysign = null;
		try {
			//签名
			mysign = SignMsg(prestr, "config/yixuntiankong.pfx", "sumpay");
		} catch (Exception e) {
			e.printStackTrace();
		}
        System.out.println("签名结果:" + mysign);
        return mysign;
    }
	
	/**
	 * 把数组所有元素排序，并按照“参数=参数值”的模式用“&”字符拼接成字符串
	 * @param params
	 * @return
	 */
	public static String createLinkString(Map<String, String> params) {
        List<String> keys = new ArrayList<String>(params.keySet());
        Collections.sort(keys);
        String prestr = "";
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = params.get(key);
            if (i == keys.size() - 1) {//拼接时，不包括最后一个&字符
                prestr = prestr + key + "=" + value;
            } else {
                prestr = prestr + key + "=" + value + "&";
            }
        }
        return prestr;
    }
	
	/**
	 * 对字符串进行签名
	 * @param TobeSigned	需要进行签名的字符串
	 * @param KeyFile		PFX证书文件路径
	 * @param PassWord		私钥保护密码
	 * @return				签名成功返回true(从LastResult属性获取结果)，失败返回false(从LastErrMsg属性获取失败原因)
	 * @throws Exception
	 */
	public String SignMsg(final String TobeSigned, final String KeyFile, final String PassWord) throws Exception {
		InputStream fiKeyFile = null;
		KeyStore ks = KeyStore.getInstance("PKCS12");
		try {
			System.out.println(FilePathUtil.getClassBuildPath());
			fiKeyFile = new FileInputStream(new File(FilePathUtil.getClassBuildPath() + KeyFile));
			ks.load(fiKeyFile, PassWord.toCharArray());
		} catch (Exception ex) {
			if (fiKeyFile != null)
				fiKeyFile.close();
			throw ex;
		}
		Enumeration myEnum = ks.aliases();
		String keyAlias = null;
		RSAPrivateCrtKey prikey = null;
		// keyAlias = (String) myEnum.nextElement();
		/* IBM JDK必须使用While循环取最后一个别名，才能得到个人私钥别名 */
		while (myEnum.hasMoreElements()) {
			keyAlias = (String) myEnum.nextElement();
			// System.out.println("keyAlias==" + keyAlias);
			if (ks.isKeyEntry(keyAlias)) {
				prikey = (RSAPrivateCrtKey) ks.getKey(keyAlias, PassWord.toCharArray());
				break;
			}
		}
		if (prikey == null) {
			throw new Exception("没有找到匹配私钥");
		} else {
			Signature sign = Signature.getInstance("SHA256withRSA");
			sign.initSign(prikey);
			sign.update(TobeSigned.getBytes("utf-8"));
			return SecurityUtil.base64Encode(sign.sign());
		}
	}
	
	@RequestMapping("tconfig.do")
	public void tongConfig(HttpServletRequest request, HttpServletResponse response){
		AgentConfig tAgentConfig = new AgentConfig();
		try {
			Map<String, String> configMap = new HashMap<String,String>();
			configMap.put("orderUrl",tAgentConfig.getOrderUrl());
			this.renderJsonData(configMap, JsonType.JSON_OBJECT, request, response);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
